package demo5

import "fmt"

// 抽象 工厂设计模式

type cooke interface {
	Cook()
}

type vegetable struct{}

func CreateVegetable() *vegetable {
	return &vegetable{}
}
func (v vegetable) Cook() {
	fmt.Println("做菜....")
}

type food struct{}

func CreateFood() *food {
	return &food{}
}
func (v food) Cook() {
	fmt.Println("做饭....")
}

type Home interface {
	ProductVegetable() cooke
	ProductFood() cooke
}

type HomeStruct struct{}

func NewHomeStruct() *HomeStruct {
	return &HomeStruct{}
}
func (h HomeStruct) ProductVegetable() cooke {
	return CreateVegetable()
}
func (h HomeStruct) ProductFood() cooke {
	return CreateFood()
}

// 外观设计模式

type windown struct{}

func NewWindown() *windown {
	return &windown{}
}
func (w windown) CloseWindow() {
	fmt.Println("关窗....")
}

type engine struct{}

func NewEngin() *engine {
	return &engine{}
}
func (e engine) Launch() {
	fmt.Println("发动....")
}

type retardation struct{}

func NewRetardation() *retardation {
	return &retardation{}
}
func (e retardation) StartOver() {
	fmt.Println("启动....")
}

type Car struct {
	windown
	engine
	retardation
}

func NewCar() *Car {
	return &Car{
		*NewWindown(),
		*NewEngin(),
		*NewRetardation(),
	}
}

func (c Car) Run() {
	c.CloseWindow()
	c.Launch()
	c.StartOver()
}

// 建造者模式

type builder interface {
	Build()
}

type supervisor struct {
	build builder
}

func NewSupervisor(b builder) *supervisor {
	return &supervisor{build: b}
}

func (s *supervisor) Press() {
	s.build.Build()
}

type construct struct {
	built bool
}

func NewConstruct() *construct {
	return &construct{}
}

func (c *construct) Build() {
	c.built = true
}

type Product struct {
	Built bool
}

func (c *construct) GetResult() *Product {
	return &Product{Built: c.built}
}

// 选项设计模式
type options struct {
	StrOption1 string
	StrOption2 string
	StrOption3 string
	IntOption1 int
	IntOption2 int
	IntOption3 int
}

// 定义规则
type optionFunc func(*options)

// 可拓展
func WithStrOption1(str string) optionFunc {
	return func(opt *options) {
		opt.StrOption1 = str
	}
}

func WithStrOption2(str string) optionFunc {
	return func(opt *options) {
		opt.StrOption2 = str
	}
}

func WithStrOption3(str string) optionFunc {
	return func(opt *options) {
		opt.StrOption3 = str
	}
}

func WithIntOption1(i int) optionFunc {
	return func(opt *options) {
		opt.IntOption1 = i
	}
}

func WithIntOption2(i int) optionFunc {
	return func(opt *options) {
		opt.IntOption2 = i
	}
}

func WithIntOption3(i int) optionFunc {
	return func(opt *options) {
		opt.IntOption3 = i
	}
}

func OptionInit(opts ...optionFunc) *options {
	var opt options
	for _, o := range opts {
		o(&opt)
	}
	return &opt
}
